/*
 * Quercia Luciano
 * Algoritmi e Strutture Dati
 * a.a. 2009-10
 */


#ifndef _CODA_H_
#define _CODA_H_

#define SIZE 100

#include "nodoQ.h"

template <class T>
class Coda {
public:
	Coda();
	~Coda();

	//operatori
	bool codaVuota();

	void fuoriCoda()      throw (char const *);
	void inCoda(T elem)   throw (char const *);
	T leggiCoda()         throw (char const *);


	//funzioni di servizio
	void print(void);
	void printAll(void);

private:
	typedef int posizione;
	posizione antetesta;
	posizione ultimo;

	NodoQ<T> vettore[ SIZE ];
};




/*****************************
 *        DEFINIZIONI        *
 *     dei metodi di Coda    *
 *****************************/


template <class T>
Coda<T>::Coda() {
	antetesta = 0 ;
	ultimo = 0 ;
}


template <class T>
Coda<T>::~Coda() {}



template <class T>
bool Coda<T>::codaVuota() {
	return (antetesta == ultimo);
}


template <class T>
void Coda<T>::inCoda(T elem) throw (char const *) {
	if ( (antetesta-ultimo) != 1 ) {
		if (ultimo-antetesta != SIZE-1) {
			ultimo++;
			ultimo %= SIZE ;

			vettore[ ultimo ].setValue( elem );
		} else
			throw "Coda piena" ;
	} else
		throw "Coda piena.";
}


template <class T>
void Coda<T>::fuoriCoda() throw (char const *) {
	if ( !codaVuota() ) {
		antetesta++;
		antetesta %= SIZE ;
	} else
		throw "Impossibile cancellare da una coda vuota" ;
}


template <class T>
T Coda<T>::leggiCoda() throw (char const *) {
	if ( !codaVuota() )
		return vettore[antetesta+1].getValue();
	else
		throw "Impossibile leggere da una coda vuota";
}



template <class T>
void Coda<T>::print(void) {
	if ( ! codaVuota() ) {
		cout << "[ " << leggiCoda() << " ]" << endl ;
	} else
		cout << "[ Empty Queue ]" << endl ;
}


template <class T>
void Coda<T>::printAll(void) {
	if ( ! codaVuota() ) {
		cout << "[ " ;
		for (int i=antetesta+1; i<=ultimo; i++)
			cout << vettore[i].getValue() << " " ;
		cout << " ]" << endl ;
	} else
		cout << "[ Empty Queue ]" << endl ;
}

#endif
